package org.example.delaytimetask;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;

import java.util.Calendar;
import java.util.Set;

/**
 * redis 实现延迟定时任务
 * @author chaigq
 * @version 1.0
 * @date 2021/8/31 2:11 下午
 */
public class RedisTask {

    private static final String ADDR = "127.0.0.1";
    private static final int PORT = 6379;

    private static JedisPool jedisPool = new JedisPool(ADDR, PORT);

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    // TODO 在高并发条件下，多消费者会取到同一个订单号

    // 模拟生产者-生成5个订单
    public void producDelayMessage(){
        for (int i = 0; i < 5; i++) {
            // 获取默认时间
            Calendar calendar = Calendar.getInstance();
            // 过期时间获取值
            calendar.add(Calendar.SECOND, 3);
            int second3later = (int) (calendar.getTimeInMillis() / 1000);
            RedisTask.getJedis().zadd("OrderId",second3later,"OID0000001"+i);
            System.out.println(System.currentTimeMillis()+"ms:redis生成了一个订单任务：订单ID为"+"OID0000001"+i);
        }
    }

    // 消费者，取订单
    public void consumerDelayMessage(){
        Jedis jedis = RedisTask.getJedis();
        while(true) {
            Set<Tuple> items = jedis.zrangeWithScores("OrderId", 0, 1);
            if (items == null || items.isEmpty()) {
                System.out.println("当前没有等待的任务");
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                continue;
            }
            int score = (int) ((Tuple) items.toArray()[0]).getScore();
            Calendar cal = Calendar.getInstance();
            int nowSecond = (int) (cal.getTimeInMillis() / 1000);
            // 判断当前时间是否大于过期时间
            if (nowSecond >= score) {
                String orderId = ((Tuple) items.toArray()[0]).getElement();
                //jedis.zrem("OrderId", orderId);
                // 在redis中查询
                Long num = jedis.zrem("OrderId", orderId);
                if( num != null && num>0){
                    System.out.println(System.currentTimeMillis() + "ms:redis消费了一个任务：消费的订单OrderId为" + orderId);
                }
            }
        }
    }

    public static void main(String[] args) {
        RedisTask appTest =new RedisTask();
        // 生产
        appTest.producDelayMessage();
        // 消费
        appTest.consumerDelayMessage();

    }

}
